#include "ArbolTrie.h"
#include "FreqDocumento.h"
#include<list>
using namespace std;

ArbolTrie::ArbolTrie() {
	this->raiz = new Nodo_ArbolTrie();
}

// Devuelve true si inserto el termino
bool ArbolTrie::insertarTermino(string termino, unsigned char *nroDocumento , unsigned char *frecuencia) {
	//le concateno el eow
	string terminoAux = termino + "/";
	int i = 0;
	char caracter;
	int size = termino.size();
	void *nodo_arbol = NULL;
	bool agregue = false;
	//unsigned char *offset_existente = NULL;
	/*
	 * antes decia ((i > size) && (caracter != '/')), no entraba nunca al while por el i > size
	 * i = 0 y size a algo positivo entonces al while no entraba nunca
	 * Me parece q, como condición solo tiene q tener (i <= size)
	 * Cuando i = size, está agregando el '/', por lo q estaría creando el nodo_hoja
	 */
	while(i <= size) {
		caracter = terminoAux[i];
		if(i == 0) {
			/*
			 * Si la raiz esta vacia o el caracter q tiene no existe
			 * lo agrego con "setCaracter" y le paso el prox caracter para ver a q nodo tiene q instanciar
			 */
			if(!(raiz->existe_caracter(caracter))) {
				// setCaracter nada mas pone el caracter q corresponda e instancia un nodo
				raiz->setCaracter(caracter);
			}
			nodo_arbol = raiz->get_SigNodo(caracter);
			// nodo_arbol será el proximo nodo, puede q se haya agregado cuando se hize setCaracter
			// o como el caracter ya estaba agregado, ya existía
		}
		/*
		 * Una vez q se inserto la primera letra, inserto las siguientes
		 */
		else if(i > 0) {
			/*
			 * Si la lista de "nodo_arbol" está vacia o el caracter q tiene no existe
			 * lo agrego con "setCaracter", agregará todos inclusive el '/' ya que con eso identfico q ese nodo de la lista
			 * apunta a un NodoHoja, si se guarda el '/' en un NodoHoja nunca se sabrá cuando viene el nodo hoja
			 * y se tendría q preguntar de q clase es perdiendo la utilidad de POO
			 */
			if(!(((Nodo_ArbolTrie*)nodo_arbol)->existe_caracter(caracter))) {
				((Nodo_ArbolTrie*)nodo_arbol)->setCaracter(caracter);
				agregue = true;
			}
			// En la ultima pasada cuando i = size, nodo_arbol sera un puntero al nodo hoja
				nodo_arbol = ((Nodo_ArbolTrie*)nodo_arbol)->get_SigNodo(caracter);
			/*
			 * nodo_arbol será el proximo nodo donde tendŕe q insertar la siguietne letra
			 * entonces cuando entre de vuelta al while, se realiza el chequeo otra vez
			 */
		}
		i++;
	}
	if((frecuencia != NULL) && (nroDocumento != NULL))
		((NodoHoja_ArbolTrie*)nodo_arbol)->setFreqDocumento(frecuencia, nroDocumento);

	return agregue;
}

/* Si encuentra el termino devuelve la lista, sino devuelve NULL
 */
list<FreqDocumento>* ArbolTrie::buscarTermino(string termino) {
	int i = 0;
	bool esta = true;
	char caracter;
	//unsigned char *offset = NULL;
	list<FreqDocumento> *freqDocList = NULL;
	//le concateno el eow
	string terminoAux = termino + "/";
	int size = termino.size();
	void *nodo_arbol = NULL;
	/*
	 * Cuando i = size - 1, esta agregando la última letra, por lo q estaría creando el nodo_hoja
	 */
	while((i <= size) && (esta)) {
		caracter = terminoAux[i];
		//std::cout << caracter << std::endl;
		if(i == 0) {
			/*
			 * Si la raiz esta vacia o el caracter q tiene no existe, ya se q el termino no está
			 */
			if(!(raiz->existe_caracter(caracter)))
				esta = false;
			if(esta)
				nodo_arbol = raiz->get_SigNodo(caracter);
			// nodo_arbol será el proximo nodo, si el termino está debería existir
		}
		/*
		 * Una vez q se busco la primera letra, busco las siguiente
		 */
		if(i > 0) {
			/*
			 * Si la lista de "nodo_arbol" está vacia o el caracter q tiene no existe, el término no está
			 */
			if(!(((Nodo_ArbolTrie*)nodo_arbol)->existe_caracter(caracter)))
				esta = false;
			// En la ultima pasada cuando i = size - 1, nodo_arbol sera un puntero al nodo hoja
			if(esta)
				nodo_arbol = ((Nodo_ArbolTrie*)nodo_arbol)->get_SigNodo(caracter);
			/*
			 * nodo_arbol será el proximo nodo donde tendŕe q buscar la siguiente letra
			 * entonces cuando entre de vuelta al while, se realiza el chequeo otra vez
			 */
		}
		i++;
	}
	if(esta)
		freqDocList = ((NodoHoja_ArbolTrie*)nodo_arbol)->getFreqDocumento();
	return freqDocList;
}


/* Si encuentra el termino devuelve la lista, sino devuelve NULL
 */
bool ArbolTrie::buscarStopword(string termino) {
	int i = 0;
	bool esta = true;
	char caracter;
	//unsigned char *offset = NULL;
	//le concateno el eow
	string terminoAux = termino + "/";
	int size = termino.size();
	void *nodo_arbol = NULL;
	/*
	 * Cuando i = size - 1, esta agregando la última letra, por lo q estaría creando el nodo_hoja
	 */
	while((i <= size) && (esta)) {
		caracter = terminoAux[i];
		//std::cout << caracter << std::endl;
		if(i == 0) {
			/*
			 * Si la raiz esta vacia o el caracter q tiene no existe, ya se q el termino no está
			 */
			if(!(raiz->existe_caracter(caracter)))
				esta = false;
			if(esta)
				nodo_arbol = raiz->get_SigNodo(caracter);
			// nodo_arbol será el proximo nodo, si el termino está debería existir
		}
		/*
		 * Una vez q se busco la primera letra, busco las siguiente
		 */
		if(i > 0) {
			/*
			 * Si la lista de "nodo_arbol" está vacia o el caracter q tiene no existe, el término no está
			 */
			if(!(((Nodo_ArbolTrie*)nodo_arbol)->existe_caracter(caracter)))
				esta = false;
			// En la ultima pasada cuando i = size - 1, nodo_arbol sera un puntero al nodo hoja
			if(esta)
				nodo_arbol = ((Nodo_ArbolTrie*)nodo_arbol)->get_SigNodo(caracter);
			/*
			 * nodo_arbol será el proximo nodo donde tendŕe q buscar la siguiente letra
			 * entonces cuando entre de vuelta al while, se realiza el chequeo otra vez
			 */
		}
		i++;
	}
	return esta;
}

void ArbolTrie::vaciarArbol() {
	raiz->vaciarNodo();
}

void ArbolTrie::recorrerArbol(std::fstream *terminos) {
	raiz->recorrer(terminos);
}

ArbolTrie::~ArbolTrie() {
	vaciarArbol();
	// eliminar la raíz es lo último q se debería hacer
	delete raiz;
}
